package com.ruoyi.system.netty;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.HexUtil;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.TBOrderDevice;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ITBDeviceService;
import com.ruoyi.system.service.ITBOrderDeviceService;
import com.ruoyi.system.service.impl.SysConfigServiceImpl;
import com.ruoyi.system.service.impl.TBOrderDeviceServiceImpl;
import com.ruoyi.system.util.DevStatus;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.ReferenceCountUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.net.InetSocketAddress;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TCPServerHandler extends SimpleChannelInboundHandler<Object> {
    public static Map<String,String>devMap=new HashMap<>();
    public static Map<String,Channel>connMap=new HashMap<>();
    private static final Logger log = LoggerFactory.getLogger(TCPServerHandler.class);
    private ITBOrderDeviceService orderDeviceService;
    private ISysConfigService configService;

    public TCPServerHandler(){
        orderDeviceService= SpringUtils.getBean(TBOrderDeviceServiceImpl.class);
        configService= SpringUtils.getBean(SysConfigServiceImpl.class);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress ipSocket = (InetSocketAddress)ctx.channel().remoteAddress();
        String clientIp = ipSocket.getAddress().getHostAddress();
        Console.log("clientIp:"+clientIp+"：：连接服务成功...");
        Console.error("start:devMap:size::"+devMap.size());
        Console.error("start:connMap:size::"+connMap.size());
        if(devMap.containsKey(clientIp)){
            Console.log("连接时，clientIp:"+clientIp+"：：已存在...");
        }else{
            Console.log("连接时，clientIp:"+clientIp+"：：不存在...");
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        InetSocketAddress ipSocket = (InetSocketAddress)ctx.channel().remoteAddress();
        String clientIp = ipSocket.getAddress().getHostAddress();
        Console.log("clientIp:"+clientIp+"：：断开连接...");
        if(devMap.containsKey(clientIp)){
            String devId=devMap.remove(clientIp);//删除掉线的连接
            Console.error("end:devMap:size::"+devMap.size());
            connMap.remove(devId);//删除连接对象
            Console.error("end:connMap:size::"+connMap.size());
            TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
            String deviceStatue = orderDevice.getDeviceStatue();
            if(DevStatus.ONLINE.equals(deviceStatue)){
                changeDevStatus(devId, DevStatus.UNLINE);//离线
            }
            if(DevStatus.WAIT_LOCK.equals(deviceStatue)){
                updateOutTime(devId);//更新离线时间
            }
        }else{
            Console.log("断开时，clientIp:"+clientIp+"：：不存在...");
        }
        ctx.channel().close();//关闭客户端连接
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception{
        ctx.channel().close();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
        InetSocketAddress ipSocket = (InetSocketAddress)ctx.channel().remoteAddress();
        String clientIp = ipSocket.getAddress().getHostAddress();
        if(msg instanceof String){
            try{
                String res = (String)msg;
                log.warn("接收到gps数据="+res);
                //分割经纬度数据
                String gps=null;
                res=res.replaceAll("\\s","");
                String[] splitStr = res.split(",");
                if(splitStr!=null&&splitStr.length>0){
                    String lng = splitStr[0].replaceAll("LNG=","");
                    String lat = splitStr[1].replaceAll("LAT=","");
                    gps=lat+","+lng;
                    log.warn("接收到数据 gps="+gps);
                }
                if(devMap.containsKey(clientIp)){
                    //更新经纬度操作
                    String devId = devMap.get(clientIp);
                    TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
                    if(orderDevice!=null&&gps!=null){
                        orderDevice.setGps(gps);//更新经纬度
                        orderDeviceService.updateTBOrderDevice(orderDevice);
                    }
                }else{
                    log.debug(clientIp+"：：ip不存在，数据遗弃...");
                }
            }catch (Exception ex){
                log.error(ex.getMessage());
            }
        }else if (msg instanceof byte[]){
            try{
                byte[] bs = (byte[])msg;
                String s = HexUtil.encodeHexStr(bs);
                log.debug("接收到锁车数据="+s);
                String devId = s.substring(6,30);
                log.warn("客户端ip:"+clientIp);
                log.warn("设备id:"+clientIp);
                devId=devId.toLowerCase();
                devMap.put(clientIp,devId);
                connMap.put(devId,ctx.channel());

                TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
                if(orderDevice!=null){
                    String deviceStatue = orderDevice.getDeviceStatue();
                    log.warn("设备状态:"+deviceStatue);
                    String isLock="fe0101"+devId+"fdfc";
                    String unLock="fe0102"+devId+"fdfc";
                    String payRes="fe0202"+devId+"fdfc";//已付款
                    String responseStr=unLock;
                    boolean paySuc=false;
                    boolean isPay = validateStatus(orderDevice.getOrderNum());
                    if(isPay){
                        paySuc=true;
                    }
                    if(DevStatus.INTEND.equals(deviceStatue)||DevStatus.UNLINE.equals(deviceStatue)){
                        changeDevStatus(devId,DevStatus.ONLINE);//在线
                    }else if(DevStatus.WAIT_LOCK.equals(deviceStatue)){
                        //待锁车，判断上次断线与本次连接之间时长，确定是否要开机就锁车
                        Date nowTime = new Date();
                        String outTime = orderDevice.getOutTime();
                        if(outTime!=null&& outTime.length()>0){
                            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                            Date _outTime = sdf.parse(outTime);
                            String LockLong = configService.selectConfigByKey("LockLong");
                            int t = Integer.parseInt(LockLong)*60*1000;
                            if(nowTime.getTime()-_outTime.getTime()>t){//离线时长大于30分钟
                                //判断设备所属订单是否付清款项
                                if(isPay){
                                    changeDevStatus(devId,DevStatus.ONLINE);//在线
                                    paySuc=true;
                                }else{
                                    changeDevStatusAndOutTime(devId,DevStatus.LOCK);//锁车并清空最后一次离线时间
                                    //锁车
                                    String lockStr="fe0101"+devId+"fdfc";
                                    ByteBuf bufff = Unpooled.buffer();
                                    //返回锁定状态
                                    bufff.writeBytes(HexUtil.decodeHex(lockStr));
                                    ctx.channel().writeAndFlush(bufff);//发送锁车指令
                                    return;
                                }
                            }else{
                                updateOutTimeEmpty(devId);
                            }
                        }
                    }else if(DevStatus.LOCK.equals(deviceStatue)){
                        //已锁定
                        //判断设备所属订单是否付清款项
                        //款项未付清
                        if(!isPay){
                            responseStr=isLock;//锁车
                        }else{
                            //分期已结清，或全款
                            responseStr=unLock;//不锁车
                            changeDevStatus(devId,DevStatus.ONLINE);//在线
                            paySuc=true;
                        }
                    }
                    if(!paySuc){
                        System.out.println("返回数据1:["+clientIp+"]"+responseStr);
                        sendMsg(ctx,responseStr);//发送是否锁车命令
                    }else{
                        System.out.println("返回数据2：["+clientIp+"]"+payRes);
                        sendMsg(ctx,payRes);//发送已付款命令
                    }
                }else{
                    Console.log(devId+"::设备订单不存在...");
                }
            }catch (Exception ex){
                log.error(ex.getMessage());
            }
        }
    }

    /**
     * 修改设备在线状态
     * @param devId
     * @param status
     */
    private void changeDevStatus(String devId,String status){
        TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
        if(orderDevice!=null){
            orderDevice.setDeviceStatue(status);
            orderDeviceService.updateTBOrderDevice(orderDevice);
        }
    }

    private void changeDevStatusAndOutTime(String devId,String status){
        TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
        if(orderDevice!=null){
            orderDevice.setDeviceStatue(status);
            orderDevice.setOutTime("");
            orderDeviceService.updateTBOrderDevice(orderDevice);
        }
    }

    private void updateOutTime(String devId){
        TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
        if(orderDevice!=null){
            orderDevice.setOutTime(DateUtil.now());
            orderDeviceService.updateTBOrderDevice(orderDevice);
        }
    }

    private void updateOutTimeEmpty(String devId){
        TBOrderDevice orderDevice = orderDeviceService.selectTBOrderDeviceByCode(devId);
        if(orderDevice!=null){
            orderDevice.setOutTime("");
            orderDeviceService.updateTBOrderDevice(orderDevice);
        }
    }

    private void sendMsg(ChannelHandlerContext ctx,String responseStr){
        ByteBuf bufff = Unpooled.buffer();
        //返回锁定状态
        bufff.writeBytes(HexUtil.decodeHex(responseStr));
        ctx.channel().writeAndFlush(bufff);
    }

    //验证是否付完款项
    private boolean validateStatus(String orderNum){
        boolean isPay = false;
        List<String> valList =  orderDeviceService.validateStatus(orderNum);
        for (String valStr : valList) {
            String[] valArr = valStr.split(",");
            if(valArr!=null&&valArr.length>0){
                String firstStr = valArr[0];
                String secondStr = valArr[1];
                if(firstStr.equals("0")){
                    isPay=true;
                    break;
                }else if("1".equals(secondStr)){
                    isPay=false;
                    break;
                }else{
                    isPay=true;
                }

            }
        }
        return isPay;
    }

}
